
package com.ys.chatserver.http.logic;

import com.eva.epc.common.util.CommonUtils;
import com.eva.framework.dbpool.DBDepend;
import com.eva.framework.dbpool.DBShell;
import com.eva.framework.utils.LoggerFactory;
import com.ys.chatserver.BaseConf;

import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

/**
 * 定时转储服务端存储的客户端的超期聊天记录、离线消息。
 *
 * @author Jason
 * @since 4.5
 */
public class TimmingRestoreMessages {
    /**
     * 将聊天记录表数据复制到聊天记录存档表的可重用SQL（重用的目的是希
     * 望别的地方用到时能保持一致，防止以后增、减字段时维护不方便）
     */
    public final static String COPY_CHATTING_MESSAGES_TO_ACHIVED_SQL =
            "INSERT INTO chat_msgs_collect_archived(src_uid,dest_uid,chat_type,msg_type,msg_content,msg_time,msg_time2,online_count,fingerprint,parent_fp)" +
                    "	 select src_uid,dest_uid,chat_type,msg_type,msg_content,msg_time,msg_time2,online_count,fingerprint,parent_fp from chat_msgs_collect";

    /**
     * 将聊天记录表数据清除的可重用SQL（重用的目的是希
     * 望别的地方用到时能保持一致，防止以后维护不方便）
     */
    public final static String DELETE_CHATTING_MESSAGES_SQL = "DELETE FROM chat_msgs_collect";

    private static TimmingRestoreMessages instance = null;

    private Timer timer = null;
    private DBShell db = new DBShell();

    public static TimmingRestoreMessages getInstance() {
        if (instance == null)
            instance = new TimmingRestoreMessages();
        return instance;
    }

    public void doTaskOnece() {
        LoggerFactory.getLog().debug("[定时器2]======= 【1/2】聊天记录、离线消息超期转储处理[开始] =======");
        long t = System.currentTimeMillis();

        try {
            Vector<Object> sqls = new Vector<>();
            Vector<Object> values = new Vector<>();


            //********************* 先尝试转储过期的聊天记录 ************************//
            // 通过SQL的函数计算数据库中聊天消息与当前时间的时间差
            String timediffSQL1 = DBDepend.getTIMEDIFF("SECOND", "msg_time");

            // 先将超出期限的聊天记录先插入到存档表中
            sqls.add(COPY_CHATTING_MESSAGES_TO_ACHIVED_SQL + " where " + timediffSQL1 + ">?");
            values.add(new Object[]{BaseConf.getInstance().getAUTO_TIMING_RESTORE_MESSAGES_TIMEOUT()});

            // 再将超出期限的聊天记录从聊天记录表中移除
            sqls.add(DELETE_CHATTING_MESSAGES_SQL + " where " + timediffSQL1 + ">?");
            values.add(new Object[]{BaseConf.getInstance().getAUTO_TIMING_RESTORE_MESSAGES_TIMEOUT()});


            //********************* 先尝试转储过期的离线消息 ************************//
            // 通过SQL的函数计算数据库中聊天消息与当前时间的时间差
            String timediffSQL2 = DBDepend.getTIMEDIFF("SECOND", "history_time");
            // 直接将超出期限的离线消息从离线消息表中移除
            sqls.add("DELETE FROM chat_offline_history where " + timediffSQL2 + ">?");
            values.add(new Object[]{BaseConf.getInstance().getAUTO_TIMING_RESTORE_MESSAGES_TIMEOUT()});


            //********************* 提交数据库执行 *********************************//
            db.update(sqls, values, true);
        } catch (Exception e) {
            LoggerFactory.getLog().warn("[定时器2]======= 聊天记录、离线消息超期转储处理过程中出现的非正常逻辑："
                    + e.getMessage() + "，原因可能是没有需要处理的数据行，您可忽略本行log。");
        }

        LoggerFactory.getLog().debug("[定时器2]======= 【2/2】聊天记录、离线消息超期转储处理[完成] ,[耗时：" + (System.currentTimeMillis() - t) + "毫秒]");
    }

    public void start() {
        // ** 先确保之前定时任务被停止
        stop();

        // ** 启动定时任务
        timer = new Timer();
        // ** 以定长延迟的方式进行（即下一次执行是在本次执行结束之后开始计时）
        timer.schedule(new TimerTask() {
                           @Override
                           public void run() {
                               doTaskOnece();
                           }
                       }
                // 首次执行时的延迟
                , 1000 * 60 * 10
                // 定时执行的时间间隔
                , CommonUtils.getIntValue(BaseConf.getInstance().getAUTO_TIMING_RESTORE_MESSAGES_INTERVAL(), 10 * 60 * 10));
    }

    /**
     * 无条件中断本定时器的运行。
     */
    public void stop() {
        if (timer != null) {
            try {
                timer.cancel();
            } finally {
                timer = null;
            }
        }
    }

    /**
     * 定时器是否正在运行中。
     *
     * @return true表示是，否则定时器处于停止状态
     */
    public boolean isRunning() {
        return timer != null;
    }
}
